import { shallowReadonly } from "../reactivity/reactive";
import { proxyRefs } from "../reactivity/ref";
import { emit } from "./componentEmit";
import { initProps } from "./componentProps";
import { PublicInstanceProxyHandlers } from "./componentPublicInstance";
import { initSlots } from "./componentSlots";



export function createComponentInstance(vnode,parent){
    // console.log("createComponentInstance",parent);
    const component = {
        vnode,
        type: vnode.type,
        next:null,//代表下次要更新的虚拟节点
        setupState:{},
        props:{},
        provides:parent?parent.provides:{},
        parent,
        slots:{},
        isMounted:false,
        emit:()=>{}
    };
    component.emit = emit.bind(null,component) as any;

    return component;

}

export function setupComponent(instance){
    // TODO
    initProps(instance,instance.vnode.props)
    initSlots(instance,instance.vnode.children);
    setupStatefulComponent(instance);

}

function setupStatefulComponent(instance: any) {
    
    
    const Component = instance.type;

    // ctx
    instance.proxy = new Proxy({_:instance},PublicInstanceProxyHandlers);

    const {setup} = Component;
    if (setup){
        setCurrentInstance(instance)
        //function Object
        const setupResult = setup(shallowReadonly(instance.props),{
            emit:instance.emit,
        });
        setCurrentInstance(null);
        
        handleSetupResult(instance,setupResult)
    }
}

function handleSetupResult(instance,setupResult:any){
    // function Object
    //TODO function
    if (typeof setupResult === "object"){
        instance.setupState = proxyRefs(setupResult);
    }

    finishComponentSetup(instance);
}

function finishComponentSetup(instance:any){
    const Component = instance.type;

    if (compiler && !Component.render){
        if (Component.template){
            Component.render = compiler(Component.template);
        }
    }

    // 此处将虚拟dom的type中的render函数绑定到component当中
    instance.render = Component.render
    
}

let currentInstance =null;

export function getCurrentInstance() {
    return currentInstance;
}

export function setCurrentInstance(instance){
    currentInstance = instance;
}

let compiler;

export function registerRuntimeCompiler(_compiler){
    compiler = _compiler;
}
